package com.baizhi.shane.shane.service.impl;

import com.baizhi.shane.common.base.Result;
import com.baizhi.shane.constant.SysMapping;
import com.baizhi.shane.enums.ResultCode;
import com.baizhi.shane.shane.dto.*;
import com.baizhi.shane.shane.entity.ShaneQuestion;
import com.baizhi.shane.shane.manager.CountVOManager;
import com.baizhi.shane.shane.vo.*;
import com.baizhi.shane.sys.manager.RedisManager;
import com.baizhi.shane.sys.utils.CommonUtils;
import com.baizhi.shane.sys.vo.IdVO;
import com.baizhi.shane.sys.vo.SuccessedOutVO;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baizhi.shane.shane.entity.ShaneAnswer;
import com.baizhi.shane.shane.service.ShaneAnswerService;
import com.baizhi.shane.shane.mapper.ShaneAnswerMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
* @author wbz12
* @description 针对表【shane_answer(啥呢回答表)】的数据库操作Service实现
* @createDate 2023-07-25 22:33:37
*/
@Service
@Slf4j
public class ShaneAnswerServiceImpl extends ServiceImpl<ShaneAnswerMapper, ShaneAnswer>
    implements ShaneAnswerService{

    @Resource
    private ShaneAnswerMapper shaneAnswerMapper;
    @Resource
    private CommonUtils commonUtils;
    @Resource
    private RedisManager redisManager;
    @Resource
    private CountVOManager countVOManager;

    /**
     * 通过关键字模糊查询回答列表
     *
     * @Author 闻柏智
     * @Date 21:27 2024/1/22
     * @Param pageInVO
     * @return java.util.List<com.baizhi.shane.shane.vo.PageAnswerOutVO>
     **/
    @Override
    public List<PageAnswerOutVO> pageByContent(PageInVO pageInVO) {
        // 转成查询DTO
        PageInDTO pageInDTO = commonUtils.pageInVOToDTO(pageInVO, null);
        // 获取回答列表
        List<PageAnswerOutDTO> pageAnswerOutDTOList = shaneAnswerMapper.pageByContent(pageInDTO);
        /* 无数据则返回空数组 */
        if (CollectionUtils.isEmpty(pageAnswerOutDTOList)) {
            return new ArrayList<>();
        }
        // 初始化返回值
        List<PageAnswerOutVO> pageAnswerOutVOList = new ArrayList<>();
        /* 提取回答ID列表 */
        List<Long> answerIdList = pageAnswerOutDTOList
                .stream()
                .map(PageAnswerOutDTO::getAnswerId)
                .collect(Collectors.toList());
        /* 获取关系集合 */
        Map<Long, CountVO> likeMap = this.getAnswerLikeCountMapByAnswerIdList(answerIdList);
        Map<Long, CountVO> againstMap = this.getAnswerAgainstCountMapByAnswerIdList(answerIdList);
        Map<Long, CountVO> collectMap = this.getAnswerCollectCountMapByAnswerIdList(answerIdList);
        Map<Long, CountVO> commentMap = this.getAnswerCommentCountMapByAnswerIdList(answerIdList);

        for (PageAnswerOutDTO pageAnswerOutDTO : pageAnswerOutDTOList) {
            // 补充关系
            PageAnswerOutVO pageAnswerOutVO = this.pageDTOToVO(pageAnswerOutDTO, likeMap, againstMap, collectMap, commentMap);
            pageAnswerOutVOList.add(pageAnswerOutVO);
        }


        return pageAnswerOutVOList;
    }

    /**
     * 分页查询回答列表的DTO转VO
     *
     * @Author 闻柏智
     * @Date 21:23 2024/1/25
     * @Param pageAnswerOutDTO
     * @Param likeMap:
     * @Param againstMap:
     * @Param collectMap:
     * @Param commentMap:
     * @return com.baizhi.shane.shane.vo.PageAnswerOutVO
     **/
    private PageAnswerOutVO pageDTOToVO (
            PageAnswerOutDTO pageAnswerOutDTO,
            Map<Long, CountVO> likeMap,
            Map<Long, CountVO> againstMap,
            Map<Long, CountVO> collectMap,
            Map<Long, CountVO> commentMap
    ) {
        PageAnswerOutVO pageAnswerOutVO = new PageAnswerOutVO();
        // 复制值
        BeanUtils.copyProperties(pageAnswerOutDTO,pageAnswerOutVO);
        // 默认评论树不显示
        pageAnswerOutVO.setShowComment(SysMapping.NOT_DISPLAY_COMMENT_TREE);
        /* 评论树空数组 */
        pageAnswerOutVO.setCommentTreeList(new ArrayList<>());
        /* 展示内容结尾加省略号 */
        String newDisplayText = pageAnswerOutDTO.getAnswerDisplayText() + SysMapping.ELLIPSIS;
        pageAnswerOutVO.setAnswerDisplayText(newDisplayText);
        /* 补充关系 */
        Long answerId = pageAnswerOutVO.getAnswerId();
        pageAnswerOutVO.setLikeCount(likeMap.get(answerId).getTheCount().longValue());
        pageAnswerOutVO.setNowUserLiked(likeMap.get(answerId).getNowUserRelIt());
        pageAnswerOutVO.setNowUserLikedRelId(likeMap.get(answerId).getNowUserRelIt());

        pageAnswerOutVO.setAgainstCount(againstMap.get(answerId).getTheCount().longValue());
        pageAnswerOutVO.setNowUserAgainsted(againstMap.get(answerId).getNowUserRelIt());
        pageAnswerOutVO.setNowUserAgainstRelId(againstMap.get(answerId).getNowUserRelIt());

        pageAnswerOutVO.setCollectCount(collectMap.get(answerId).getTheCount().longValue());
        pageAnswerOutVO.setNowUserCollected(collectMap.get(answerId).getNowUserRelIt());
        pageAnswerOutVO.setNowUserCollectedRelId(collectMap.get(answerId).getNowUserRelIt());

        pageAnswerOutVO.setCommentCount(commentMap.get(answerId).getTheCount().longValue());
        pageAnswerOutVO.setNowUserCommented(commentMap.get(answerId).getNowUserRelIt());
        pageAnswerOutVO.setNowUserCollectedRelId(commentMap.get(answerId).getNowUserRelIt());

        pageAnswerOutVO.setCommentTreeList(new ArrayList<>());
        return pageAnswerOutVO;

    }

    /**
     * 通过问题ID列表查询这些问题的点赞数量
     *
     * @Author 闻柏智
     * @Date 20:29 2024/1/21
     * @Param answerIdList
     * @return java.util.List<com.baizhi.shane.shane.vo.CountVO>
     **/
    @Override
    public List<CountVO> getAnswerLikeCountByAnswerIdList(List<Long> answerIdList) {
        Long userId = this.redisManager.getUserId();
        List<CountVO> countVOList = this.shaneAnswerMapper.getAnswerLikeCountByAnswerIdList(answerIdList, userId);
        return countVOList;
    }

    /**
     * 通过回答ID查询单个回答的点赞数量
     *
     * @Author 闻柏智
     * @Date 20:35 2024/1/21
     * @Param answerId
     * @return com.baizhi.shane.shane.vo.CountVO
     **/
    @Override
    public CountVO getOneAnswerLikeCountByAnswerId(Long answerId) {
        List<Long> answerIdList = new ArrayList<Long>() {{
            add(answerId);
        }};
        List<CountVO> countVOList = this.getAnswerLikeCountByAnswerIdList(answerIdList);
        CountVO countVO = countVOManager.countVOListToOneVO(countVOList, answerId);
        return countVO;
    }

    /**
     * 通过回答ID查询单个回答的点赞数量，并且转化成Map
     *
     * @Author 闻柏智
     * @Date 20:40 2024/1/21
     * @Param answerIdList
     * @return java.util.Map<java.lang.Long,com.baizhi.shane.shane.vo.CountVO>
     **/
    @Override
    public Map<Long, CountVO> getAnswerLikeCountMapByAnswerIdList(List<Long> answerIdList) {
        List<CountVO> answerLikeCountByAnswerIdList = this.getAnswerLikeCountByAnswerIdList(answerIdList);
        Map<Long, CountVO> likeMap = answerLikeCountByAnswerIdList
                .stream()
                .collect(Collectors.toMap(
                        CountVO::getEntityId, // Key属性
                        Function.identity()  // Value属性
                ));

        return likeMap;
    }

    /**
     * 通过回答ID列表查询这些回答的反对数量
     *
     * @Author 闻柏智
     * @Date 21:01 2024/1/21
     * @Param answerIdList
     * @return java.util.List<com.baizhi.shane.shane.vo.CountVO>
     **/
    @Override
    public List<CountVO> getAnswerAgainstCountByAnswerIdList(List<Long> answerIdList) {
        Long userId = this.redisManager.getUserId();
        List<CountVO> countVOList = this.shaneAnswerMapper.getAnswerAgainstCountByAnswerIdList(answerIdList, userId);
        return countVOList;
    }

    /**
     * 通过回答ID查询单个回答的反对数量
     *
     * @Author 闻柏智
     * @Date 21:03 2024/1/21
     * @Param answerId
     * @return com.baizhi.shane.shane.vo.CountVO
     **/
    @Override
    public CountVO getOneAnswerAgainstCountByAnswerId(Long answerId) {
        List<Long> answerIdList = new ArrayList<Long>() {{
            add(answerId);
        }};
        List<CountVO> countVOList = this.getAnswerAgainstCountByAnswerIdList(answerIdList);
        CountVO countVO = countVOManager.countVOListToOneVO(countVOList, answerId);
        return countVO;
    }

    /**
     * 通过问题ID列表查询这些问题的点赞数量，并且转化为Map
     *
     * @Author 闻柏智
     * @Date 21:05 2024/1/21
     * @Param answerIdList
     * @return java.util.Map<java.lang.Long,com.baizhi.shane.shane.vo.CountVO>
     **/
    @Override
    public Map<Long, CountVO> getAnswerAgainstCountMapByAnswerIdList(List<Long> answerIdList) {
        List<CountVO> answerMapCountByAnswerIdList = this.getAnswerAgainstCountByAnswerIdList(answerIdList);
        Map<Long, CountVO> againstMap = answerMapCountByAnswerIdList
                .stream()
                .collect(Collectors.toMap(
                        CountVO::getEntityId, // Key属性
                        Function.identity()  // Value属性
                ));

        return againstMap;
    }

    /**
     * 通过回答ID列表查询这些回答的收藏数量
     *
     * @Author 闻柏智
     * @Date 15:27 2024/1/22
     * @Param answerIdList
     * @return java.util.List<com.baizhi.shane.shane.vo.CountVO>
     **/
    @Override
    public List<CountVO> getAnswerCollectCountByAnswerIdList(List<Long> answerIdList) {
        Long userId = this.redisManager.getUserId();
        List<CountVO> countVOList = this.shaneAnswerMapper.getAnswerCollectCountByAnswerIdList(answerIdList, userId);
        return countVOList;
    }

    /**
     * 通过回答ID列表查询这些回答的收藏数量，并且转为Map
     *
     * @Author 闻柏智
     * @Date 15:30 2024/1/22
     * @Param answerIdList
     * @return java.util.Map<java.lang.Long,com.baizhi.shane.shane.vo.CountVO>
     **/
    @Override
    public Map<Long, CountVO> getAnswerCollectCountMapByAnswerIdList(List<Long> answerIdList) {
        List<CountVO> answerMapCountByAnswerIdList = this.getAnswerCollectCountByAnswerIdList(answerIdList);
        Map<Long, CountVO> collectMap = answerMapCountByAnswerIdList
                .stream()
                .collect(Collectors.toMap(
                        CountVO::getEntityId, // Key属性
                        Function.identity()  // Value属性
                ));
        return collectMap;
    }

    /**
     * 通过回答ID查询单个回答的收藏数量
     *
     * @Author 闻柏智
     * @Date 15:33 2024/1/22
     * @Param answerId
     * @return com.baizhi.shane.shane.vo.CountVO
     **/
    @Override
    public CountVO getOneAnswerCollectCountByAnswerId(Long answerId) {
        List<Long> answerIdList = new ArrayList<Long>() {{
            add(answerId);
        }};
        List<CountVO> countVOList = this.getAnswerCollectCountByAnswerIdList(answerIdList);
        CountVO countVO = countVOManager.countVOListToOneVO(countVOList, answerId);
        return countVO;
    }

    /**
     * 通过回答ID列表查询这些回答的评论数量
     *
     * @Author 闻柏智
     * @Date 15:37 2024/1/22
     * @Param answerIdList
     * @return java.util.List<com.baizhi.shane.shane.vo.CountVO>
     **/
    @Override
    public List<CountVO> getAnswerCommentCountByAnswerIdList(List<Long> answerIdList) {
        Long userId = this.redisManager.getUserId();
        List<CountVO> countVOList = this.shaneAnswerMapper.getAnswerCommentCountByAnswerIdList(answerIdList, userId);
        return countVOList;
    }

    /**
     * 通过回答ID列表查询这些回答的评论数量
     *
     * @Author 闻柏智
     * @Date 15:39 2024/1/22
     * @Param answerIdList
     * @return java.util.Map<java.lang.Long,com.baizhi.shane.shane.vo.CountVO>
     **/
    @Override
    public Map<Long, CountVO> getAnswerCommentCountMapByAnswerIdList(List<Long> answerIdList) {
        List<CountVO> answerMapCountByAnswerIdList = this.getAnswerCommentCountByAnswerIdList(answerIdList);
        Map<Long, CountVO> commentMap = answerMapCountByAnswerIdList
                .stream()
                .collect(Collectors.toMap(
                        CountVO::getEntityId, // Key属性
                        Function.identity()  // Value属性
                ));
        return commentMap;
    }

    /**
     * 通过回答ID列表查询这些回答的评论数量
     *
     * @Author 闻柏智
     * @Date 15:41 2024/1/22
     * @Param answerId
     * @return com.baizhi.shane.shane.vo.CountVO
     **/
    @Override
    public CountVO getOneAnswerCommentCountByAnswerId(Long answerId) {
        List<Long> answerIdList = new ArrayList<Long>() {{
            add(answerId);
        }};
        List<CountVO> countVOList = this.getAnswerCommentCountByAnswerIdList(answerIdList);
        CountVO countVO = countVOManager.countVOListToOneVO(countVOList, answerId);
        return countVO;
    }

    /**
     * 通过ID查询单个回答信息
     *
     * @Author 闻柏智
     * @Date 16:11 2024/2/29
     * @Param answerId
     * @return com.baizhi.shane.shane.vo.GetOneAnswerOutVO
     **/
    @Override
    public GetOneAnswerOutVO getOneAnswerById(Long answerId) {

        // 查询
        GetOneAnswerOutDTO getOneAnswerOutDTO = this.shaneAnswerMapper.getOneAnswerById(answerId);
        // 初始化返回值
        GetOneAnswerOutVO getOneAnswerOutVO = new GetOneAnswerOutVO();
        // 复制属性
        BeanUtils.copyProperties(getOneAnswerOutDTO, getOneAnswerOutVO);

        /* 获取关系 */
        CountVO likeVO = this.getOneAnswerLikeCountByAnswerId(answerId);
        CountVO collectVO = this.getOneAnswerCollectCountByAnswerId(answerId);
        CountVO commentVO = this.getOneAnswerCommentCountByAnswerId(answerId);

        /* 赋值关系值 */
        getOneAnswerOutVO.setLikeCount(likeVO.getTheCount().longValue());
        getOneAnswerOutVO.setCollectCount(collectVO.getTheCount().longValue());
        getOneAnswerOutVO.setCommentCount(commentVO.getTheCount().longValue());
        getOneAnswerOutVO.setNowUserLiked(likeVO.getNowUserRelIt());
        getOneAnswerOutVO.setNowUserCollected(collectVO.getNowUserRelIt());
        getOneAnswerOutVO.setNowUserCommented(commentVO.getNowUserRelIt());
        getOneAnswerOutVO.setNowUserLikedRelId(likeVO.getNowUserRelId());
        getOneAnswerOutVO.setNowUserCollectedRelId(collectVO.getNowUserRelId());

        // 评论树默认不显示
        getOneAnswerOutVO.setShowComment(0l);

        return getOneAnswerOutVO;
    }

    /**
     * 新增一个回答
     *
     * @Author 闻柏智
     * @Date 17:14 2024/3/1
     * @Param answerInsertInVO
     * @return com.baizhi.shane.sys.vo.SuccessedOutVO
     **/
    @Override
    public SuccessedOutVO insertOne(AnswerInsertInVO answerInsertInVO) {

        if (answerInsertInVO == null) {
            Result.fail(ResultCode.PARAM_IS_INVALID);
        }
        ShaneAnswer shaneAnswer = new ShaneAnswer();
        BeanUtils.copyProperties(answerInsertInVO, shaneAnswer);

        shaneAnswer.setDisplayText(StringUtils.substring(shaneAnswer.getPlainText(), 0, 100));
        shaneAnswer.setUserId(redisManager.getUserId());
        if (shaneAnswer.getStatus() == null) {
            shaneAnswer.setStatus(SysMapping.STATUS_PUBLISHED);
        }

        boolean successed = this.save(shaneAnswer);
        SuccessedOutVO successedOutVO =
                commonUtils.boolToSuccessedOutVO(successed, SysMapping.INSERT_ANSWER_SUCCESS, SysMapping.INSERT_ANSWER_FAIL);

        return successedOutVO;
        
    }

    /**
     * 我发布过的回答
     *
     * @Author 闻柏智
     * @Date 21:32 2024/3/3
     * @Param
     * @return java.util.List<com.baizhi.shane.shane.dto.AnswerMyPostedOutDTO>
     **/
    @Override
    public List<AnswerMyPostedOutDTO> myPosted() {
        Long userId = redisManager.getUserId();
        List<AnswerMyPostedOutDTO> answerMyPostedOutDTOList = this.shaneAnswerMapper.myPosted(userId);
        return answerMyPostedOutDTOList;
    }

    /**
     * 通过ID编辑回答
     *
     * @Author 闻柏智
     * @Date 22:43 2024/3/3
     * @Param shaneAnswer
     * @return com.baizhi.shane.sys.vo.SuccessedOutVO
     **/
    @Override
    public SuccessedOutVO updateOneById(ShaneAnswer shaneAnswer) {
        shaneAnswer.setDisplayText(StringUtils.substring(shaneAnswer.getPlainText(), 0, 100));
        boolean successed = this.updateById(shaneAnswer);
        SuccessedOutVO successedOutVO =
                commonUtils.boolToSuccessedOutVO(successed, SysMapping.CHANGE_SUCCESS, SysMapping.CHANGE_FAIL);
        return successedOutVO;
    }

    /**
     * 我收藏的回答
     *
     * @Author 闻柏智
     * @Date 14:33 2024/3/4
     * @Param
     * @return java.util.List<com.baizhi.shane.shane.entity.ShaneAnswer>
     **/
    @Override
    public List<AnswerMyPostedOutDTO> myCollected() {
        // 获取当前登陆人ID
        Long userId = redisManager.getUserId();
        List<AnswerMyPostedOutDTO> shaneAnswerList = shaneAnswerMapper.myCollected(userId);
        return shaneAnswerList;
    }

    /**
     * 通过回答ID列表查询这些回答的标签列表
     *
     * @Author 闻柏智
     * @Date 15:23 2024/3/4
     * @Param idListStr
     * @return java.util.List<com.baizhi.shane.shane.vo.AnswerLabelOutVO>
     **/
    @Override
    public List<AnswerLabelOutVO> getAnswerLabelListByAnswerIdList(String idListStr) {
        // 入参字符串转为Long列表
        List<Long> answerIdList = commonUtils.idListStrToLongList(idListStr);
        // 从数据库查数据
        List<AnswerLabelOutDTO> answerLabelOutDTOList =
                this.shaneAnswerMapper.getAnswerLabelListByAnswerIdList(answerIdList);
        /* 按照问题ID分组 */
        Map<Long, List<AnswerLabelOutDTO>> idEntityMap = answerLabelOutDTOList
                .stream()
                .collect(Collectors.groupingBy(AnswerLabelOutDTO::getAnswerId));
        // 提取问题ID集合
        Set<Long> answerIdSet = idEntityMap.keySet();
        // 创建VO列表
        List<AnswerLabelOutVO> answerLabelOutVOList = new ArrayList<>();
        /* 构建返回值列表 */
        for (Long answerId : answerIdSet) {
            AnswerLabelOutVO answerLabelOutVO = new AnswerLabelOutVO();
            answerLabelOutVO.setAnswerLabelOutDTOList(new ArrayList<>());
            List<AnswerLabelOutDTO> labelList = idEntityMap.get(answerId);
            answerLabelOutVO.setAnswerId(answerId);
            if (!CollectionUtils.isEmpty(labelList)) {
                answerLabelOutVO.setAnswerLabelOutDTOList(labelList);
            }
            answerLabelOutVOList.add(answerLabelOutVO);

        }
        return answerLabelOutVOList;
    }

    /**
     * 通过回答ID查询单个回答的标签
     *
     * @Author 闻柏智
     * @Date 15:38 2024/3/4
     * @Param answerId
     * @return com.baizhi.shane.shane.vo.AnswerLabelOutVO
     **/
    @Override
    public AnswerLabelOutVO getAnswerLabelByAnswerId(Long answerId) {
        String idListStr = answerId.toString() + SysMapping.COMMA;
        List<AnswerLabelOutVO> answerLabelOutVOList = this.getAnswerLabelListByAnswerIdList(idListStr);
        if (CollectionUtils.isEmpty(answerLabelOutVOList)) {
            return new AnswerLabelOutVO();
        }
        AnswerLabelOutVO answerLabelOutVO = answerLabelOutVOList.get(0);
        return answerLabelOutVO;
    }

    /**
     * 通过关键字查询回答列表的元素数量和分页个数
     *
     * @Author 闻柏智
     * @Date 16:06 2024/3/4
     * @Param pageInVO
     * @return com.baizhi.shane.shane.vo.CountAndPageOutVO
     **/
    @Override
    public CountAndPageOutVO countAndPageByContent(PageInVO pageInVO) {
        String content = pageInVO.getContent();
        Integer pageSize = pageInVO.getPageSize();
        if (pageSize == null) {
            pageSize = 10;
        }
        double pageSizeDouble = pageSize.doubleValue();
        Integer count = this.shaneAnswerMapper.countAndPageByContent(content);

        int pageCountInt = (int) Math.ceil(count / pageSizeDouble);
        Integer pageCount = pageCountInt;

        CountAndPageOutVO countAndPageOutVO = new CountAndPageOutVO();
        countAndPageOutVO.setMaxCount(count);
        countAndPageOutVO.setPageCount(pageCount);

        return countAndPageOutVO;
    }

    /**
     * 删除一个回答-通过ID
     *
     * @Author 闻柏智
     * @Date 16:13 2024/3/4
     * @Param idVO
     * @return com.baizhi.shane.sys.vo.SuccessedOutVO
     **/
    @Override
    public SuccessedOutVO deleteOneAnswerById(IdVO idVO) {
        Long id = idVO.getId();
        boolean success = this.removeById(id);
        SuccessedOutVO successedOutVO = commonUtils.boolToSuccessedOutVO(success, null, null);
        return successedOutVO;
    }
}




